#include <stdio.h>
#include <liburing.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define ENTRES_LENGTH 1024
#define BUFFER_LENGTH 1024

#define EVENT_ACCEPT    0
#define EVENT_READ      1
#define EVENT_WRITE     2
struct CONN_INFO
{
    int fd;
    int event;
};

int Init_server(int port)
{
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in sockserver;
    memset(&sockserver, 0, sizeof(sockserver));
    sockserver.sin_family = AF_INET;
    sockserver.sin_addr.s_addr = inet_addr("192.168.100.200");
    sockserver.sin_port = htons(port);
    bind(listenfd, (struct sockaddr *)&sockserver, sizeof(struct sockaddr_in));

    listen(listenfd, 10);
    //printf("listenfd：%d\n", listenfd);
    return listenfd;
}

void set_accept_event(struct io_uring* uring,int fd,struct sockaddr_in *clientaddr,socklen_t *len)
{
    struct io_uring_sqe * sqe = io_uring_get_sqe(uring);

    struct CONN_INFO accept_info = {
        .fd = fd,
        .event = EVENT_ACCEPT,
    };
    io_uring_prep_accept(sqe,fd,(struct sockaddr*)clientaddr,len,0);
    memcpy(&sqe->user_data,&accept_info,sizeof(struct CONN_INFO));
}

void set_event_recv(struct io_uring* uring,int sockfd,void *buf, size_t len, int flags)
{
    struct io_uring_sqe * sqe = io_uring_get_sqe(uring);
    struct CONN_INFO read_info = {
        .fd = sockfd,
        .event = EVENT_READ,
    };
    io_uring_prep_recv(sqe,sockfd,buf,len,flags);
    memcpy(&sqe->user_data,&read_info,sizeof(struct CONN_INFO));
}

void set_event_send(struct io_uring* uring,int sockfd,void *buf, size_t len, int flags)
{
    struct io_uring_sqe * sqe = io_uring_get_sqe(uring);
    struct CONN_INFO send_info = {
        .fd = sockfd,
        .event = EVENT_WRITE,
    };
    io_uring_prep_send(sqe,sockfd,buf,len,flags);
    memcpy(&sqe->user_data,&send_info,sizeof(struct CONN_INFO));
}

int main()
{
    int sockfd = Init_server(9999);

    struct io_uring_params params;
    memset(&params,0,sizeof(params));

    struct io_uring uring;
    io_uring_queue_init_params(ENTRES_LENGTH,&uring,&params);

    struct sockaddr_in clientaddr;
    socklen_t len = sizeof(clientaddr);
    set_accept_event(&uring,sockfd,&clientaddr,&len);

    char buffer[BUFFER_LENGTH] = {0};
    while (1)
    {
        io_uring_submit(&uring);

        struct io_uring_cqe* cqe;
        io_uring_wait_cqe(&uring,&cqe);

        struct io_uring_cqe* cqes[128];
        int nready = io_uring_peek_batch_cqe(&uring,cqes,128);

        for (int i = 0; i < nready; i++)
        {
            struct io_uring_cqe *cqee = cqes[i];
            struct CONN_INFO info;
            memcpy(&info,&cqee->user_data,sizeof(struct CONN_INFO));

            if (info.event == EVENT_ACCEPT)
            {
                //printf("io_uring_peek_batch_cqe EVENT_ACCEPT\n");
                int clientfd = cqee->res;
                set_accept_event(&uring,sockfd,&clientaddr,&len);
                set_event_recv(&uring,clientfd,buffer,BUFFER_LENGTH,0);
            }
            else if (info.event == EVENT_READ)
            {
                int ret = cqee->res;//当是read时，返回可读字节数
                //printf("RECV-%d:%s\n",ret,buffer);
                if(ret == 0)
                {
                    close(info.fd);//解决断开时一直打印问题
                }
                else if (ret > 0)
                {
                    set_event_recv(&uring,info.fd,buffer,BUFFER_LENGTH,0);
                    set_event_send(&uring,info.fd,buffer,ret,0);
                }
            }
            else if (info.event == EVENT_WRITE)
            {
                int ret = cqee->res;
                //printf("SEND-%d:%s\n",ret,buffer);
            }
        }
        
        // 标记事件已处理（必须调用！）
        // io_uring_cqe_seen(&uring, cqe);
        io_uring_cq_advance(&uring,nready); // 批量标记已处理
    }
    return 0;
}

